var Consts = require('../../../util/consts');

var killerUserDao = require('../../../dao/killer/killerUserDao');
var gameService = require('../../../services/killer/gameService');
var messageService = require('../../../services/messageService');
var KillerHandler = require('./entryHandler');
var logger = require('pomelo-logger').getLogger('KillerGame', __filename);
var TimeDelayTrigger = require('../../../domain/common/timeDelayTrigger');

module.exports = function (app) {
    return new VoteHandler(app);
};


var VoteHandler = function (app) {
    this.app = app;
    this.allVotes = {};
    this.allVoteResults = {};
    this.allReadyUsers = {};

    this.timeDelayTriggers = {};
};
var handler = VoteHandler.prototype;

var admin = 'backgroundAdmin';

handler.finishSpeak = function (msg, session, next) {
    var self = this;
    var username = msg.username;
    var rid = session.get('rid');
    if (!self.allReadyUsers[rid]) {
        self.allReadyUsers[rid] = [];
    }
    self.allReadyUsers[rid].push(username);

    killerUserDao.getAliveUsersByRid(rid, function (err, users) {
        if (err) {
            logger.error("finish speak error. rid:%j, error: %j", rid, err);
            next(null, {code: 500, msg: 'finish spear error'});
        } else {
            if (users.length === self.allReadyUsers[rid].length) {
                var aliveUsers = [];
                for (var iter = 0; iter < users.length; iter++) {
                    var myUser = users[iter];
                    aliveUsers.push({username: myUser.name, seq: myUser.seq});
                }
                // 所有玩家结束发言，广播消息，进入投票环节
                self._sendMessage(admin, '*', {
                    action: Consts.KillerAction.START_VOTE,
                    users: aliveUsers
                }, rid);
                self.allReadyUsers[rid] = [];

                // 开始投票计时
                self._startVoteTiming(rid);

                next(null, {
                    code: 200,
                    msg: 'start vote'
                });
            } else {
                next(null, {code: 200});
            }
        }
    });
};
/**
 * 30 seconds
 * @private
 */
handler._startVoteTiming = function (rid) {
    var self = this;
    var timeDelayTrigger = new TimeDelayTrigger(30 * 1000);
    this.timeDelayTriggers[rid] = timeDelayTrigger;
    timeDelayTrigger.run(function () {
        killerUserDao.getAliveUsersByRid(rid, function (err, users) {
            if (err) {
                logger.error("startVoteTiming error: %j", err);
            } else {
                self._checkVoteResult(users, rid, null);
            }
        });
    });
};

handler._sendMessage = function (from, target, content, rid) {
    var self = this;
    var action = content.action || '';
    messageService.sendMessageWithAction(from, target, JSON.stringify(content), rid,
        Consts.GameRoute.KILLER_GAME, self.app, action);
};

/**
 *
 * @param msg {voter:投票者, target:被投的人}
 * @param session
 * @param next
 */
handler.voteOne = function (msg, session, next) {
    var self = this;
    var app = self.app;
    var voter = msg.voter;
    var target = msg.target;
    var rid = session.get('rid');
    if (!self.allVotes[rid]) {
        self.allVotes[rid] = [];
        self.allVoteResults[rid] = [];
    }
    if (self.allVotes[rid].indexOf(voter) > -1) {
        next(null, {code: 200, msg: 'already vote, please wait'});
        return;
    }
    self.allVotes[rid].push(voter);
    self.allVoteResults[rid].push(target);
    killerUserDao.getAliveUsersByRid(rid, function (err, users) {
        if (err) {
            next(null, {
                code: 400
            });
        } else {
            if (users.length === self.allVotes[rid].length) {

                // 关闭投票计时器
                if (self.timeDelayTriggers[rid]) {
                    self.timeDelayTriggers[rid].close();
                }

                self._checkVoteResult(users, rid, next);

            } else {
                next(null, {
                    code: 200,
                    msg: 'wait others vote'
                });
            }
        }
    })
};

handler._checkVoteResult = function (aliveUsers, rid, next) {
    var self = this;
    var users = aliveUsers;

    var userDict = {};
    for (var i = 0; i < users.length; i++) {
        var user = users[i];
        userDict[user.name] = user;
    }

    // 所有人都已经投过票
    var votes = self.allVoteResults[rid];
    var voteDict = {};
    for (var i = 0; i < votes.length; i++) {
        var target = votes[i];
        if (voteDict[target] === undefined) {
            voteDict[target] = 0;
        }
        voteDict[target] = voteDict[target] + 1;
    }
    var maxVote = 0;
    var maxVoteUser = '';
    var voteStatistic = [];
    var differTime = 0;
    for (var username in voteDict) {
        voteStatistic.push({
            username: username,
            seq: userDict[username].seq,
            voteCount: voteDict[username] || 0
        });
        if (voteDict[username] > maxVote) {
            maxVote = voteDict[username];
            maxVoteUser = username;
            differTime += 1;
        }
    }
    // 多个人被投票，而且maxVote只变过一次
    if (differTime === 1 && Object.keys(voteDict) > 1) {
        // 通知房间里面的其他人，谁被投出去了
        self._sendMessage(admin, '*', {
            action: Consts.KillerAction.VOTE_OUT,
            username: 'none',
            seq: -1,
            voteStatistic: voteStatistic
        }, rid);
        // 清空，准备下一轮
        self.allVotes[rid] = [];
        self.allVoteResults[rid] = [];

        self._sendMessage(admin, '*', {
            action: Consts.KillerAction.NEXT_CYCLE
        }, rid);
        // 重新分发mark
        var killerHandler = new KillerHandler(self.app);
        killerHandler.dispatchMarks(rid);
        if (next) {
            next(null, {
                code: 200
            });
        }
    } else {
        // someone get killed
        killerUserDao.killUser(rid, maxVoteUser, function (err, user) {
            if (err) {
                console.error("kill user failed: " + err);
                if (next) {
                    next(null, {
                        code: 500,
                        msg: 'kill user failed'
                    });
                }
            } else {
                // 通知房间里面的其他人，谁被投出去了

                self._sendMessage(admin, '*', {
                    action: Consts.KillerAction.VOTE_OUT,
                    username: maxVoteUser,
                    seq: userDict[maxVoteUser].seq,
                    voteStatistic: voteStatistic
                }, rid);
                // 清空，准备下一轮
                self.allVotes[rid] = [];
                self.allVoteResults[rid] = [];

                // 判断比赛结果
                gameService.checkGameStatus(rid, function (err, code, winners) {
                    if (err) {
                        if (next) {
                            next(null, {
                                code: 500,
                                msg: 'check game status error'
                            });
                        }
                    } else {
                        if (code === gameService.GameStatus.KILLER_WIN) {
                            self._sendMessage(admin, '*', {
                                winner: Consts.KillerRole.KILLER,
                                action: Consts.KillerAction.GAME_OVER,
                                usernames: winners
                            }, rid);
                        } else if (code === gameService.GameStatus.COMMONER_WIN) {
                            self._sendMessage(admin, '*', {
                                winner: Consts.KillerRole.COMMONER,
                                action: Consts.KillerAction.GAME_OVER,
                                usernames: winners
                            }, rid);
                        } else {
                            self._sendMessage(admin, '*', {
                                action: Consts.KillerAction.NEXT_CYCLE
                            }, rid);
                            // 重新分发mark
                            var killerHandler = new KillerHandler(self.app);
                            killerHandler.dispatchMarks(rid);
                        }
                        if (next) {
                            next(null, {
                                code: 200
                            });
                        }
                    }
                });
            }
        });
    }
};